#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <sys/uio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include "list.h"

#define TCP_PORT   6874
#define UDP_PORT	9967
#define RESPONSE_PORT   7674
#define RESPONSE_UDP_PORT   9767
#define TIME_PORT	8345
#define BUFLEN 8192

struct thread_data{
	int socket;
	char * ipClient;
};

struct sensore{
	int id;
	char mac[17];
	int rfcomm;
	int canale;
	char *value; //di tipo char perchè il sensore potrebbe restituire più di un intero!
	char attivo; //'s'=connessione a dispositivo bluetooth avvenuta con successo. 'n'=il contrario!
	int rate; //serve per simulare le diverse velocità dei sensori
};

//coda di richieste provenienti da wifi & tutti i relativi semafori e mutex
dati_t *queue;
sem_t full;// empty verificava se ci sn spazi liberi nella coda, full verifica se ci sn spazi pieni 
pthread_mutex_t mutex;

//coda di risposte da mandare ai nodi wifi e tutti i relativi semafori e mutex
dati_t *queue_resp;
sem_t full_resp;
pthread_mutex_t mutex_resp;

//mutex per i vari thread BLUETOOTH:
pthread_mutex_t M; /* def.mutex condiviso tra threads */

//mutex per controllare le DEADLINE scadute:
pthread_mutex_t expired_d;
//contatore del numero di deadline scadute successivamente
int deadlineExpired;

//vettore di "sensori" letti da file
struct sensore *s;
int numSensori; //contatore di numSensori


//lista funzioni
void *connect_to_sensor_bluetooth(void *arg);
void *request_listener_aperiodic();
void *request_handling(void * arg);
void *request_listener_periodic();
void *sincronized_handler();
void *master_bluetooth_function();
void *send_responce_to_wifi();
void *mode_1_to_receive_bluetooth_value(void * arg);
char serial_port_exists(struct sensore *mioSensore);
void *manager_bluetooth(void * arg);


main()
{
	/*
	//faccio un sudo all'inizio, così poi vale per sempre! :D
	int error_2 = system("sudo -v");
	if(error_2 == -1){
		printf("\nErrore - PASSWORD SBAGLIATA!\n");
		return(-1);
	}*/
	
	//Creazione coda per accodare le richieste proveniente di wifi
	queue=NULL;
	printf("Coda per request creata!\n");
	//set mutex e semafori per coda di richieste
	pthread_mutex_init(&mutex,NULL);
	sem_init(&full,0,0);
	printf("Mutex e Semafori request creati!\n");
	
	
	//Creazione coda per accodare le risposte da mandare ai nodi wifi
	queue_resp = NULL;
	printf("Coda per responce creata!\n");
	//set mutex e semafori per coda di risposte
	pthread_mutex_init(&mutex_resp,NULL);
	sem_init(&full_resp,0,0);
	printf("Mutex e Semafori responce creati!\n");
	
	//mutex per contenere i valori dei sensori letti dal Bluetooth
	pthread_mutex_init(&M,NULL);
	
	//mutex per controllare il numero di deadline scadute
	pthread_mutex_init(&expired_d,NULL);
	deadlineExpired = 0; //contatore
	
	//creazione tutti i thread:
	pthread_t manager,listener,master_bluetooth,sender,writerBluetooth,udp_listener,sincro;
	pthread_create(&manager,NULL,manager_bluetooth,NULL);
	sleep(7);
	pthread_create(&listener,NULL,request_listener_periodic,NULL);
	pthread_create(&udp_listener,NULL,request_listener_aperiodic,NULL);
	pthread_create(&master_bluetooth,NULL,master_bluetooth_function,NULL);
	pthread_create(&sender,NULL,send_responce_to_wifi,NULL);
	pthread_create(&sincro,NULL,sincronized_handler,NULL);		
	
	pthread_exit(0);

}

void *manager_bluetooth(void * arg){
	//lettura degli ID + MAC dei sensori da FILE
	FILE *pf= fopen("config.txt", "r");
	if (pf == NULL){
	      printf("Non posso aprire il file! BYE!");
	      exit(-1);
	}

	numSensori=0;
	
	s = (struct sensore *)malloc(sizeof(struct sensore)); //alloco il primo elemento del vettore
	
	int jj=0;
	while(!feof(pf)){
		if(jj!=0){
			s = (struct sensore *)realloc(s,(numSensori+1)*sizeof(struct sensore));		
		}
		
		//riempio la struttura di sensori
		fscanf(pf, "ID:%d\tMAC:%s\tRFCOMM:%d\tCANALE:%d\n",&(s[numSensori].id),(s[numSensori].mac),&(s[numSensori].rfcomm),&(s[numSensori].canale));
		(s[numSensori].value) = "0";
		(s[numSensori].attivo) = 'u';
		(s[numSensori].rate) = (random()%5);
		printf("ID:%d\tMAC:%s\tRFCOMM:%d\tCANALE:%d\tVALUE:%s\n",(s[numSensori].id),(s[numSensori].mac),(s[numSensori].rfcomm),(s[numSensori].canale),s[numSensori].value);
		
		//creo tanti thread quanti sono i numSensori --> scopo: aprire le connessioni bluetooth!
		pthread_t connectorBluetooth;
		pthread_create(&connectorBluetooth,NULL,connect_to_sensor_bluetooth,(void *)&s[numSensori]);
		
		numSensori++;
		jj++;
	}
	fclose(pf);

	sleep(7);

	int indice=0;
	for(indice=0;indice<numSensori;indice++){
		if(s[indice].attivo=='u'){
			//se sono qui, vuol dire che il sensore è attivo e la soekris si è connessa tramite bluetooth
			//sleep(5);
			//printf("\nCreo writerBluetooth\n");
			pthread_t writerBluetooth;
			pthread_create(&writerBluetooth,NULL,mode_1_to_receive_bluetooth_value,(void *)&s[indice]);
		}
	}

	while(1){
		for(indice=0;indice<numSensori;indice++){
			if(s[indice].attivo=='n'){
				pthread_t connectorBluetooth;
				pthread_create(&connectorBluetooth,NULL,connect_to_sensor_bluetooth,(void *)&s[indice]);
				sleep(5);

				if(serial_port_exists(&s[indice])=='s'){
					pthread_t writerBluetooth;
					pthread_create(&writerBluetooth,NULL,mode_1_to_receive_bluetooth_value,(void *)&s[indice]);
				}//fine if
			}//fine if
		}//fine for

	}
}


char serial_port_exists(struct sensore *mioSensore){
	char nomeFile[15];
	sprintf(nomeFile,"/dev/rfcomm%d",mioSensore->rfcomm);
	//printf("\nnomeFile: %s\n",nomeFile);

	int fd= open(nomeFile, O_RDWR|O_NOCTTY|O_NDELAY);
	if (fd == -1){
		mioSensore->attivo='n';
		//printf("open_port: Unable to open /dev/rfcomm%d ",mioSensore->rfcomm);
		return 'n';
	}
	else{
		mioSensore->attivo='s';
		return 's';
	}
}

/*
Thread che sta ESEGUENDO il comando di shell.
Ovviamente se ho N sensori... avrò anche N di questi thread... ognuno prova a connettersi ad un diverso dispositivo bluetooth.
Se il dispositivo bluetooth non è attivo viene settato: mioSensore->attivo='n';
*/

void *connect_to_sensor_bluetooth(void *arg){

	//printf ("\nCreato connector to bluetooth\n");

	struct sensore *mioSensore = (struct sensore *)arg;

	//char *shell_command = malloc(sizeof("sudo rfcomm -i hci0 connect ")) + malloc(sizeof(rfcomm2));
	char *shell_command = malloc(sizeof("rfcomm -i hci0 connect ") + sizeof(mioSensore->rfcomm) + sizeof(" ") + sizeof(mioSensore->mac) + sizeof(" ") + sizeof(mioSensore->canale));
	sprintf(shell_command,"rfcomm -i hci0 connect %d %s %d",mioSensore->rfcomm,mioSensore->mac,mioSensore->canale);
	
	//printf("\nfine strcat: %s\n",shell_command);

	int err = system(shell_command);
	if(err == -1 || err == 0){
		//printf("\nErrore - NON è possibile connettersi al sensore con MAC address: %s\n",mioSensore->mac);
		mioSensore->attivo='n';
	}
		
	pthread_exit(0);
}



/*
Thread che sta in ascolto sulla porta "TCP_PORT" e crea workerThread. 
*/
void *request_listener_periodic(){
	int sockfd, newsockfd, clilen;
	struct sockaddr_in cli_addr, serv_addr;
	pthread_t thread_listener_request;

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		printf("server: can't open stream socket\n");

	memset((char *) &serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(TCP_PORT);
	
	if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
		printf("server: can't bind local address\n");	
	
	listen(sockfd, 200);
	
	printf("Listener Periodic Creato e Socket creata\n");

	while(1){
		clilen = sizeof(cli_addr);
		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
		//printf("\n\nprta client: %d\n\n",cli_addr.sin_port);
		if(newsockfd < 0)
			printf("server: accept error\n");
		
		struct sockaddr_in s;
	        int s_len = sizeof(s);
	        char ip[20];
		inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,ip,s_len);
		//printf("IP DEL CLIENT: %s\n",ip);
		struct thread_data dati_tmp;
		dati_tmp.socket = newsockfd;
		dati_tmp.ipClient = ip;
		
		/* create a new thread to process the incomming request  inet_ntoa(cli_addr.sin_addr)*/
		pthread_create(&thread_listener_request,NULL,request_handling,((void *)&dati_tmp ));
		
		/* the server is now free to accept another socket request */
	}
}//fine request_listener()


/*
WorkerThread.
quando una wifi fa la connect al socket, si crea questo thread che si occupa di eseguire (in ordine) le seguenti operazioni:
- riceve le richieste da parte della wifi (quelle del tipo "idMsg,IdSensore");
- le inserisce in coda;
- controlla lo stato della coda di richieste (perchè potrebbe essere quasi piena).
- manda un messaggio alla wifi per informarla dello stato delal coda ed eventualmente chiederle di rallentare (i messaggi, come detto nel file wifi.c sono di 3 tipi: ACK, 1/2, 3/4).
- riesegue il ciclo di attesa del nuovo messaggio ovviamente però se il messaggio ottenuto è diverso dalla stringa "END//////"
(Questo thread è quindi il produttore di richieste!).
*/
void *request_handling(void * arg){
	int ultimiFive = 0;

	struct thread_data *datii = (struct thread_data *)arg;
	char * ip = datii->ipClient;
	int socketClient = datii->socket;


	//printf("Child thread: Socket number = %d\n",  socketClient);
	//printf("Child thread: IP Client = %s\n", ip);

	struct tm* newtime;
	time_t t;	
	time(&t);
	newtime=localtime(&t);
	printf("anno:%d, mese:%d, giorno:%d, ora:%d, minuti:%d, secondi: %d",newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
	char time_master[4];

	char stringa[BUFLEN];	
	while(1){

	read(socketClient, stringa, BUFLEN);
	//printf("\n\nstringa: %s", stringa);
	if(strcmp(stringa, "TIME")==0){

		char *msg=malloc(sizeof(newtime->tm_year)+sizeof(',')+sizeof(newtime->tm_mon)+sizeof(',')+sizeof(newtime->tm_mday)+sizeof(',')+sizeof(newtime->tm_hour)+sizeof(',')+sizeof(newtime->tm_min)+sizeof(',')+sizeof(newtime->tm_sec));
		sprintf(msg ,"%d,%d,%d,%d,%d,%d", newtime->tm_year,1+newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
		printf("\nTimestamp [periodico] inviato: %s\n", msg);		
		send(socketClient,msg,strlen(msg),0);
	}else{
	
		int numMsg;
		int idSensore;
		int anno_pacch;
		int mese_pacch;
		int giorno_pacch;
		int ora_pacch;
		int minuti_pacch;
		int secondi_pacch;
		int deadline;
			
		sscanf(stringa,"%d,%d,%d,%d,%d,%d,%d,%d,%d", &numMsg,&idSensore, &anno_pacch,&mese_pacch,&giorno_pacch, &ora_pacch,&minuti_pacch, &secondi_pacch,&deadline);
		printf("\n#-- Ricevuto pacchetto relativo a traffico periodico --#");
		printf("\nNumero pacchetto: %d",numMsg);
		printf("\nID sensore : %d",idSensore);
		printf("\nIP client: %s",ip);	
		printf("\nAnno: %d", anno_pacch);
		printf("\nMese: %d", mese_pacch);
		printf("\nGiorno: %d", giorno_pacch);
		printf("\nOra: %d", ora_pacch);
		printf("\nMinuti: %d", minuti_pacch);
		printf("\nSecondi: %d", secondi_pacch);
		printf("\nDeadline: %d", deadline);
		printf("\n#------------- FINE -------------#\n\n");


		dati_t tmp;
		tmp.msgNumber = numMsg;
		tmp.sensorID = idSensore;
		tmp.sensorValue = "0";
		tmp.destinationIP = ip;
		tmp.anno = anno_pacch+1900;;
		tmp.mese = mese_pacch;
		tmp.giorno = giorno_pacch;
		tmp.ora = ora_pacch;
		tmp.minuti = minuti_pacch;
		tmp.secondi = secondi_pacch;
		tmp.deadline = deadline;
		tmp.type = "Per";
		tmp.next = NULL;
	
		//acquisisco il lock ed entro in sezione critica
		pthread_mutex_lock(&mutex); 
		//inserisco l'elemento in coda
		//printf("prima dell'inserimento\n");
		queue=insert_order_by_deadline(queue,tmp);
		//stampa(queue);
		//printf("dopo dell'inserimento\n");
		//ottengo il numero di elementi prensenti attualmente in coda
		int num_pacchetti_attuali = get_num_elements(queue);
		//printf("num_pacchetti_attuali:%d \n",num_pacchetti_attuali);
		// USCIAMO DALLA SEZIONE CRITICA: Abbiamo finito di operare sulla coda, quindi possiamo liberare il mutex
		pthread_mutex_unlock(&mutex);
		// Incremento il valore del semaforo "full"
		sem_post(&full);

		pthread_mutex_lock(&expired_d);
		int actualDeadlineExpired = deadlineExpired;
		pthread_mutex_unlock(&expired_d);
		
		int moduloFive = actualDeadlineExpired % 5; //se il resto è ZERO vuol dire che devo inviare un messaggio diverso dal semplice "ACK"
		if(moduloFive==0){
			//Mando un MSG che rallenta o velocizza la wifi
			if(ultimiFive > actualDeadlineExpired){
				//ES: 5 > 0 --> Vuol dire che devo mandare un MSG per VELOCIZZARE la wifi
				send(socketClient,"SPEED_INCREASES",sizeof("SPEED_INCREASES"),0);					
			}else{
				//ES: 5 < 10 --> Vuol dire che devo mandare un MSG per RALLENTARE la wifi
				send(socketClient,"SPEED_DECREASE",sizeof("SPEED_DECREASE"),0);					
			}
			ultimiFive = actualDeadlineExpired; //aggiorno il valore di "ultimiFive"
		}else{
			//mando ACK
			send(socketClient,"ACK",sizeof("ACK"),0);					
		}
	}

	}//fine ciclo infinito
	
	
	//close the socket and exit this thread
	close(socketClient);
	pthread_exit((void *)0);
}//fine request_handling



void *request_listener_aperiodic(){
	int ultimiFive = 0;
	struct sockaddr_in si_me;
	int s, i;
	struct sockaddr_in si_other;
	int slen=sizeof(si_other);
	char buf[BUFLEN];
	
	if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
		printf("\nError UDP socket\n");

	int broadcast=1;
	setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));

	memset((char *) &si_me, 0, sizeof(si_me));
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(UDP_PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	
	
	if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me))==-1)
		printf("\nError UDP bind\n");
		
		
	while(1){

		if (recvfrom(s, buf, BUFLEN , 0, (struct sockaddr *) &si_other, &slen)==-1)
				printf("\nError in UDP recvfrom()\n");
		
		//printf("\nReceived packet!\nData: %s\n\n", buf);
		
		struct tm* atime;
		time_t at;	
		time(&at);
		atime=localtime(&at);
		printf("\n\nActual Time Soekris:%d,%d,%d,%d,%d,%d\n\n", atime->tm_year,atime->tm_mon,atime->tm_mday,atime->tm_hour,atime->tm_min,atime->tm_sec);
			
		//ricavo l'indirizzo ip del client
		struct sockaddr_in s_s;
		int s_len = sizeof(s_s);
		char ip[20];
		inet_ntop(AF_INET,&si_other.sin_addr.s_addr,ip,s_len);
		//printf("\nIP DEL CLIENT: %s\n",ip);
		
		int numMsg;
		int idSensore;
		int anno_pacch;
		int mese_pacch;
		int giorno_pacch;
		int ora_pacch;
		int minuti_pacch;
		int secondi_pacch;
		int deadline;
		
		//printf("\nLunghezza in caratteri della stringa ottenuta: %d",strlen(buf));
		
		sscanf(buf,"%d,%d,%d,%d,%d,%d,%d,%d,%d", &numMsg,&idSensore, &anno_pacch,&mese_pacch,&giorno_pacch, &ora_pacch,&minuti_pacch, &secondi_pacch,&deadline);
		
		
		dati_t tmp;
		tmp.msgNumber = numMsg;
		tmp.sensorID = idSensore;
		tmp.sensorValue = "0";
		tmp.destinationIP = ip;
		tmp.anno = anno_pacch+1900;
		tmp.mese = mese_pacch;
		tmp.giorno = giorno_pacch;
		tmp.ora = ora_pacch;
		tmp.minuti = minuti_pacch;
		tmp.secondi = secondi_pacch;
		tmp.deadline = deadline;
		tmp.type = "Ape";
		tmp.next = NULL;
		
		printf("\n#-- PACCHETTO APERIODICO --#");
		printf("\nNumero pacchetto: %d",numMsg);
		printf("\nID sensore : %d",idSensore);
		printf("\nIP client: %s",ip);	
		printf("\nAnno: %d", anno_pacch+1900);
		printf("\nMese: %d", mese_pacch);
		printf("\nGiorno: %d", giorno_pacch);
		printf("\nOra: %d", ora_pacch);
		printf("\nMinuti: %d", minuti_pacch);
		printf("\nSecondi: %d", secondi_pacch);
		printf("\nDeadline: %d", deadline);
		printf("\n#------------- FINE -------------#\n\n");

		//verifico che la coda non è piena
		//sem_wait(&empty);
		//acquisisco il lock ed entro in sezione critica
		pthread_mutex_lock(&mutex); 
		//inserisco l'elemento in coda
		queue=insert_order_by_deadline(queue,tmp);
		//stampa(queue);
		//ottengo il numero di elementi prensenti attualmente in coda
		int num_pacchetti_attuali = get_num_elements(queue);
		//printf("num_pacchetti_attuali:%d \n",num_pacchetti_attuali);
		// USCIAMO DALLA SEZIONE CRITICA: Abbiamo finito di operare sulla coda, quindi possiamo liberare il mutex
		pthread_mutex_unlock(&mutex);
		// Incremento il valore del semaforo "full"
		sem_post(&full);
		
		/*
		TEORICAMENTE DOVREI INVIARE UN ACK PER DIRE ---> HO RICEVUTO IL PACCHETTO --> MA LE FUNZIONI DEI SOCKET SONO BLOCCANTI -->
		--> QUINDI ORA COME ORA NON SERVE MANDARE ACK!
		*/
		
		pthread_mutex_lock(&expired_d);
		int actualDeadlineExpired = deadlineExpired;
		pthread_mutex_unlock(&expired_d);
		
		int moduloFive = actualDeadlineExpired % 5; //se il resto è ZERO vuol dire che devo inviare un messaggio diverso dal semplice "ACK"
		if(moduloFive==0){
			//Mando un MSG che rallenta o velocizza la wifi
			if(ultimiFive > actualDeadlineExpired){
				//ES: 5 > 0 --> Vuol dire che devo mandare un MSG per VELOCIZZARE la wifi
				if (sendto(s, "SPEED_INCREASES", sizeof("SPEED_INCREASES"), 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP SPEED_INCREASES\n");
			}else{
				//ES: 5 < 10 --> Vuol dire che devo mandare un MSG per RALLENTARE la wifi
				if (sendto(s, "SPEED_DECREASE", sizeof("SPEED_DECREASE"), 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP SPEED_DECREASE\n");
			}
			ultimiFive = actualDeadlineExpired; //aggiorno il valore di "ultimiFive"
		}else{
			//mando ACK
			if (sendto(s, "ACK", sizeof("ACK"), 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP ACK\n");
		}

			
		
		
	}//fine ciclo infinito
	
}

void *sincronized_handler(){

	printf("\nThread di Sincronizzazione creato\n");

	struct sockaddr_in si_me;
	int s, i;
	struct sockaddr_in si_other;
	int slen=sizeof(si_other);
	char buf[BUFLEN];
	
	if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
		printf("\nError UDP socket\n");

	int broadcast=1;
	setsockopt(s, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));

	memset((char *) &si_me, 0, sizeof(si_me));
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(TIME_PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	
	
	if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me))==-1)
		printf("\nError UDP bind\n");
		
		
	while(1){

		if (recvfrom(s, buf, BUFLEN , 0, (struct sockaddr *) &si_other, &slen)==-1)
				printf("\nError in UDP recvfrom()\n");
		
		//printf("\nReceived packet!\nData: %s\n\n", buf);
		
		struct tm* atime;
		time_t at;	
		time(&at);
		atime=localtime(&at);
		printf("\n\nActual Time Soekris:%d,%d,%d,%d,%d,%d\n\n", atime->tm_year,atime->tm_mon,atime->tm_mday,atime->tm_hour,atime->tm_min,atime->tm_sec);
		
		int idTime;
		
		sscanf(buf,"TIME-%d", &idTime);
	
		//se sono qui, la richiesta è di avere il TIMESTAMP
		/*int s_2 = (random()%5+1);
		printf("\nValore sleep: %d\n",s_2);
		sleep(s_2);*/
		struct tm* newtime;
		time_t t;	
		time(&t);
		newtime=localtime(&t);
	
		char msg[BUFLEN];
	
		sprintf(msg ,"TIME-%d:%d,%d,%d,%d,%d,%d", idTime,newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);

		if (sendto(s, msg, BUFLEN, 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
			printf("\nError in sendto UDP TIMESTAMP\n");
		
		printf("\nTIME send: %s\n",msg);

	
		
	}//fine while(1)

}


/*
Thread che si occupa di :
- prelevare un elemento dalla coda di richieste (è quindi il consumatore di richieste).
- in base all'idSensore, legge dalal struttura "struct sensore *s" il giusto valore del sensore.
- inserisce una "struct dati_t" dentro la coda di risposte (è quindi produttore di risposte).
*/
void *master_bluetooth_function(){

	printf("Creazione Master Bluetooth\n");

	dati_t *dati;
	dati = (dati_t*) malloc(sizeof(dati_t));
	
	while(1){

		// verifico se c'è almeno un elemento in coda (altrimenti mi blocco)
		sem_wait (&full);
		// ENTRIAMO IN SEZIONE CRITICA: Otteniamo l'accesso esclusivo alla coda
		pthread_mutex_lock(&mutex);
		//estraggo elemento e il suo valore lo ritrovo dentro la variabile "dati"
		queue = remove_from_tail(queue,dati);
		//stampa(queue);
		// USCIAMO DALLA SEZIONE CRITICA: Abbiamo finito di operare sulla coda... IL valore di mutex ritorna da 0 a 1
		pthread_mutex_unlock(&mutex);
		// Segnaliamo di aver svuotato di un elemento la coda (ovvero, incrementiamo il valore del semaforo "empty")
		//sem_post(&empty);


		/***************************************  inizio lettura valore bluetooth ******************************/
		

		int value_sensore = -1;
		//int numSensori = sizeof(struct sensore);
		int i=0;
		pthread_mutex_lock(&M);
		for(i=0;i<numSensori;i++){
			if(s[i].id == dati->sensorID && s[i].attivo == 's'){
				value_sensore = atoi(s[i].value); //conversione da char ad int
				sleep(s[i].rate); //serve per simulare le diverse velocità dei sensori
			}
		}
		printf("\nValore letto dal sensore: %d\n",value_sensore);
		pthread_mutex_unlock(&M);
		
		
		//conversione da int --> a char
		char jj[4];
		sprintf(jj,"%d",value_sensore);
	
		dati->sensorValue = jj;
		
		/***************************************  fine lettura valore bluetooth ******************************/
		
		dati_t tmp;
		tmp.msgNumber = dati->msgNumber;
		tmp.sensorID = dati->sensorID;
		tmp.sensorValue = dati->sensorValue;
		tmp.destinationIP = dati->destinationIP;
		tmp.anno = dati->anno;
		tmp.mese = dati->mese;
		tmp.giorno = dati->giorno;
		tmp.ora = dati->ora;
		tmp.minuti = dati->minuti;
		tmp.secondi = dati->secondi;
		tmp.deadline = dati->deadline;
		tmp.type = dati->type;
		tmp.next = dati->next;
		
		//verifico che la coda di responce non è piena
		//sem_wait(&empty_resp);
		//acquisisco il lock ed entro in sezione critica
		pthread_mutex_lock(&mutex_resp); 
		//inserisco l'elemento in coda
		queue_resp = insert_order_by_deadline(queue_resp,tmp);
		//stampa(queue_resp);
		int num_valori=get_num_elements(queue_resp);
		//printf("num_valori coda risposte: %d\n",num_valori);
		// USCIAMO DALLA SEZIONE CRITICA: Abbiamo finito di operare sulla coda, quindi possiamo liberare il mutex
		pthread_mutex_unlock(&mutex_resp);
		// Incremento il valore del semaforo "full"
		sem_post(&full_resp); 
	

	}
}//fine master_bluetooth_function

/*
Thread che si occupa di "comunicare" con i sensori Bluetooth.
in realtà legge da una specifica seriale /dev/rfcomN.
Per cui per ogni connessione bluetooth ATTIVA verso un certo sensore, avrò uno di questi thread che legge i valori dalla seriale!
I valori che legge li usa per aggiornare la variabile "mioSensore->value" (NB: essendo "mioSensore" una struct condivisa tra tread, ho la necessità di usare mutex!)
PS: Domani vi posto un nuovo modo di comunicare tra soekris e bluetooth... :P
*/
void *mode_1_to_receive_bluetooth_value(void * arg)
{ 
	//ottengo l'intera struttura contenente tutti i dati sul "mioSensore".
	struct sensore *mioSensore = (struct sensore *)arg;
	
	int counter = 0;
	
	int error=0;
	char buf[5]={0};

	char nomeFile[15];
	sprintf(nomeFile,"/dev/rfcomm%d",mioSensore->rfcomm);
	printf("\nnomeFile: %s\n",nomeFile);

	int fd= open(nomeFile, O_RDWR|O_NOCTTY|O_NDELAY);
	if (fd == -1){
		mioSensore->attivo='n';
		//printf("open_port: Unable to open /dev/rfcomm%d ",mioSensore->rfcomm);
	}
	else{
		printf("\nWriterBluetooth CREATO... l'id del mio sensore è: %d !\n",mioSensore->id);
		mioSensore->attivo='s';
		while(mioSensore->attivo=='s'){
		fcntl(fd, F_SETFL, 0);
		read(fd, buf, 5);
		//int alue = atoi(buf); //conversione da char ad int
			//printf("['%d', %d]\n", alue, error);

		  if ( error < 0 ){
			printf("[er]\n");
			return 0;
		  }else{    
			pthread_mutex_lock(&M); /*prologo sez. critica */
			//value[mioSensore] = atoi(buf); //conversione da char ad int
			mioSensore->value=buf;
			printf("io, thread %d sto scrivendo: ['%s', %d]\n", mioSensore->id, mioSensore->value, error);
			pthread_mutex_unlock(&M); /*epilogo sez. critica*/
		  }
		}
	}

	printf("\n\nERRORE! NON è possibile stabilire la connessione con il sensore: %s\n\n",mioSensore->mac);
	pthread_exit(0);
}


/*
Thread che si occupa di mandare le risposte alla wifi (è quindi il consumatore di risposte).
Se c'è almeno 1 risposta in coda: apre il socket, manda in serie "idMsg"-"idSensore"-"sensorValue" e chiude il socket.
*/
void *send_responce_to_wifi(){
	dati_t *responce;
	responce = (dati_t*) malloc(sizeof(dati_t));

	while(1){
		// verifico se c'è almeno un elemento in coda (altrimenti mi blocco)
		sem_wait(&full_resp);
		// ENTRIAMO IN SEZIONE CRITICA: Otteniamo l'accesso esclusivo alla coda
		pthread_mutex_lock(&mutex_resp);
		//estraggo elemento e il suo valore lo ritrovo dentro la variabile "idSensoreBluetooth"
		queue_resp = remove_from_tail(queue_resp,responce);
		//stampa(queue_resp);
		// USCIAMO DALLA SEZIONE CRITICA: Abbiamo finito di operare sulla coda... IL valore di mutex ritorna da 0 a 1
		pthread_mutex_unlock(&mutex_resp);
		// Segnaliamo di aver svuotato di un elemento la coda (ovvero, incrementiamo il valore del semaforo "empty")
		//sem_post(&empty_resp);


		if(responce->type=="Per"){
			//CON PACCHETTO PERIODICO:
		
			int sd; /* Il socket descriptor del client */
			struct sockaddr_in server_addr; /* l'indirizzo del server */
			char buff[BUFLEN]; /* dati di invio e ricezione */
		
			/* Utilizzando la struttura hostent si definisce l'indirizzo del server */
			struct hostent *hp;
			hp = gethostbyname(responce->destinationIP);
		 
			server_addr.sin_family = AF_INET;
			server_addr.sin_port = htons(RESPONSE_PORT);
			/* successivamente viene memorizzato nella struttura server_addr */
			server_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr;
		 
			/* Viene creato il socket descriptor */
			if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
				printf("Errore nella creazione della socket\n");
		 
			/* Viene connesso al server */
			if(connect(sd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
				printf("Errore di connessione al server\n");


			printf("responce.msgNumber:%d ,responce.sensorID:%d ,responce.sensorValue:%s\n",responce->msgNumber,responce->sensorID,responce->sensorValue);
			time_t actualTime, packetTime;	
			time(&actualTime);
			struct tm* time_ac;
			time_ac=localtime(&actualTime);
			
			//printf("response time: %d,%d,%d,%d,%d,%d",(responce->anno - 1900),(responce->mese - 1),responce->giorno,(responce->ora ),responce->minuti,responce->secondi);	

			struct tm* newtime = (struct tm*)malloc(sizeof(struct tm));
			time(&packetTime);
			newtime=localtime(&packetTime);
			newtime->tm_year = (responce->anno - 1900);
			newtime->tm_mon = (responce->mese - 1);
			newtime->tm_mday = responce->giorno;
			newtime->tm_hour = (responce->ora );
			newtime->tm_min = responce->minuti;
			newtime->tm_sec = responce->secondi;
			packetTime = mktime(newtime);
			
			printf("\nnewtime --> anno:%d, mese:%d, giorno:%d, ora:%d, minuti:%d, secondi: %d",newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
			printf("\ntime_ac --> anno:%d, mese:%d, giorno:%d, ora:%d, minuti:%d, secondi: %d",time_ac->tm_year,time_ac->tm_mon,time_ac->tm_mday,time_ac->tm_hour,time_ac->tm_min,time_ac->tm_sec);
			
			//printf("\npacketTime: %ld",packetTime);
			//printf("\nactualTime: %ld",actualTime);
			
			double confronto = difftime(actualTime,packetTime);
			//printf("\nConfronto tra date (in sec.): %.2lf\n",confronto);
			
			int confrontoInt = (int) (confronto + 0.5);
			printf("\n\nTempo trascorso tra invio pacchetto da parte di wifi e costruzione della risposta da parte della soekris: %d",confrontoInt);
			printf("\nDeadline del pacchetto: %d\n\n",responce->deadline);
			
			//Se confrontoInt <= response->deadline --> invio il pacchetto: [ msgID, sensorID, sensorValue]	
			//Se confrontoInt > response->deadline --> la deadline è scaduta! Mando: [ msgID, sensorID, "EXPIRED"]

			if(confrontoInt <= responce->deadline){
				char *res=malloc(sizeof(responce->msgNumber)+sizeof(',')+sizeof(responce->sensorID)+sizeof(',')+sizeof(responce->sensorValue));
				sprintf(res,"%d,%d,%s", responce->msgNumber,responce->sensorID,responce->sensorValue);
				printf("Messaggio di rsp alla wifi: %s", res);		
				send(sd,res,strlen(res),0);				
				pthread_mutex_lock(&expired_d);
				if(deadlineExpired!=0){
					//non voglio valore NULLO
					deadlineExpired--;
				}
				pthread_mutex_unlock(&expired_d);
			}else{
				char *res=malloc(sizeof(responce->msgNumber)+sizeof(',')+sizeof(responce->sensorID)+sizeof(',')+sizeof("EXPIRED"));
				sprintf(res,"%d,%d,%s", responce->msgNumber,responce->sensorID,"EXPIRED");
				printf("Messaggio di rsp alla wifi: %s", res);		
				send(sd,res,strlen(res),0);
				pthread_mutex_lock(&expired_d);
				deadlineExpired++;
				pthread_mutex_unlock(&expired_d);
			}
			close(sd);


		}else{

			//con pacchetto APERIODICO:
			printf("\nPACCHETTO APERIODICO!!!\n");
			
			struct sockaddr_in si_other;
			int s, i, slen=sizeof(si_other);

			memset((char *) &si_other, 0, sizeof(si_other));
			si_other.sin_family = AF_INET;
			si_other.sin_port = htons(RESPONSE_UDP_PORT);
			struct hostent *hp_upd;
			hp_upd = gethostbyname(responce->destinationIP);
			si_other.sin_addr.s_addr = ((struct in_addr*)(hp_upd->h_addr)) -> s_addr;
	
			//Viene creato il socket descriptor
			if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
				printf("Errore nella creazione della socket\n");
			
			//sleep(5);
			//printf("response time: %d,%d,%d,%d,%d,%d",(responce->anno - 1900),(responce->mese - 1),responce->giorno,(responce->ora ),responce->minuti,responce->secondi);			


			time_t actualTime, packetTime;	
			time(&actualTime);
			struct tm* time_ac;
			time_ac=localtime(&actualTime);
			
			struct tm* newtime = (struct tm*)malloc(sizeof(struct tm));
			time(&packetTime);
			newtime=localtime(&packetTime);//localtime converte un time_t in 1 struct tm, mktime fa il contrario
			newtime->tm_year = (responce->anno - 1900);//time ritorna un time_t che è il current time
			newtime->tm_mon = (responce->mese - 1);
			newtime->tm_mday = responce->giorno;
			newtime->tm_hour = (responce->ora );
			newtime->tm_min = responce->minuti;
			newtime->tm_sec = responce->secondi;
			packetTime = mktime(newtime);
			
			printf("\nnewtime --> anno:%d, mese:%d, giorno:%d, ora:%d, minuti:%d, secondi: %d",newtime->tm_year,newtime->tm_mon,newtime->tm_mday,newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
			printf("\ntime_ac --> anno:%d, mese:%d, giorno:%d, ora:%d, minuti:%d, secondi: %d",time_ac->tm_year,time_ac->tm_mon,time_ac->tm_mday,time_ac->tm_hour,time_ac->tm_min,time_ac->tm_sec);
			
			//printf("\npacketTime: %ld",packetTime);
			//printf("\nactualTime: %ld",actualTime);
			
			double confronto = difftime(actualTime,packetTime);
			//printf("\nConfronto tra date (in sec.): %.2lf\n",confronto);
			
			/*Supponi di avere due valori double
			x1 = 2.1
			x2 = 2.6
			In generale, se tu li converti con un semplice cast in int, ottieni in entrambi i casi che il loro valore è 2 (intero inferiore)
			Facciamo la prova aggiungendo ora 0.5 (visto che sono entrambi positivi):
			- x1 = 2.1 diventa 2.6 e dopo il cast diventa ancora 2
			- x2 = 2.6 diventa 3.1 e dopo il cast diventa 3!
			*/
			int confrontoInt = (int) (confronto + 0.5);
			printf("\n\nTempo trascorso tra invio pacchetto da parte di wifi e costruzione della risposta da parte della soekris: %d",confrontoInt);
			printf("\nDeadline del pacchetto: %d\n\n",responce->deadline);
			
			//Se confrontoInt <= response->deadline --> invio il pacchetto: [ msgID, sensorID, sensorValue]	
			//Se confrontoInt > response->deadline --> la deadline è scaduta! Mando: [ msgID, sensorID, "EXPIRED"]
			
			char *numMsg = malloc(sizeof(responce->msgNumber));
			sprintf(numMsg, "%d",responce->msgNumber);
			if (sendto(s, numMsg, sizeof(numMsg), 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
				printf("\nError in sendto UDP numMsg\n");
			char *idS = malloc(sizeof(responce->sensorID));
			sprintf(idS, "%d",responce->sensorID);
			if (sendto(s, idS, sizeof(idS), 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
				printf("\nError in sendto UDP idS\n");
			if(confrontoInt <= responce->deadline){
				if (sendto(s, responce->sensorValue , sizeof(responce->sensorValue) , 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP TIMESTAMP\n");
				printf("\n\n--> Pacchetto di risposta! Ho inviato: [%s,%s,%s] <--\n",numMsg,idS,responce->sensorValue);
				pthread_mutex_lock(&expired_d);
				if(deadlineExpired!=0){
					//non voglio valore NULLO
					deadlineExpired--;
				}
				pthread_mutex_unlock(&expired_d);
			}else{
				if (sendto(s, "EXPIRED" , sizeof("EXPIRED") , 0, (struct sockaddr *) &si_other, sizeof(si_other))==-1)
					printf("\nError in sendto UDP TIMESTAMP\n");
				printf("\n\n--> Pacchetto di risposta! Ho inviato: [%s,%s,EXPIRED] <--\n",numMsg,idS);
				pthread_mutex_lock(&expired_d);
				deadlineExpired++;
				pthread_mutex_unlock(&expired_d);
			}
			//printf("\nMessaggio inviato!");
			
			close(s);
		
		}
		
		//printf("\n\n inviooo risposta\n\n");
		
	} 
	//pthread_exit(0);
}//fine send_responce_to_wifi
